﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Intorise.Net;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Intorise.Common;
using System.Text.RegularExpressions;

namespace TestWindowsFormsApplication.Analyzer
{
    public class EmsAnalyzer : IFreightInfoAnalyse
    {
        public bool GetDataUndelived { get; set; }
        protected string TRACK_URL = "http://www.17track.net/r/handlertrack.ashx?callback=a&num={0}&pt=0&cm=0&cc=0&_={1}";//17track查询请求url
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        private Regex regex = new Regex(@"\d+");

        public virtual FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo();
            string queryUrl = string.Format(TRACK_URL, orderNo, DateTime.Now.Ticks);////ems等查询
            var request = tools.SendRequest(queryUrl, "GET");
            string html = "";
            try
            {
                html = tools.GetResponseHtmlGzip(request);
            }
            catch (WebException ex)
            {
                client.DownloadString("http://www.17track.net/zh-cn/result/post-details.shtml?nums=EV984404871CN");
                throw ex;
            }

            var json = html.Replace("a(", "").Replace(")", "");
            var result = JsonConvert.DeserializeObject<Result>(json);
            request.Abort();
            if (result.Msg != "Ok")
            {
                info.Status = "查询出错"; return info;
            }

            if (result.dat.E != 40)//不等于40，未签收
            {
                info.Status = "n";
                if (GetDataUndelived)
                {

                }
                else if (result.dat.E != 10 || !result.dat.Z0.z.Contains("Delivered"))
                {
                    return info;
                }
                else
                {
                    info.Status = "y";
                }
            }
            else
            {
                info.Status = "y";//已妥投
            }

            if (result.dat.Z1 == null) { result.dat.Z1 = new List<Item>(0); }
            if (result.dat.Z2 == null) { result.dat.Z2 = new List<Item>(0); }
            List<DateTime?> times = new List<DateTime?>(result.dat.Z1.Count + result.dat.Z2.Count);
            times.AddRange((from xx in result.dat.Z1 select xx.a).ToList());
            times.AddRange((from xx in result.dat.Z2 select xx.a).ToList());
            info.ShipDate = times.Min();
            if (GetDataUndelived)
            {
                info.ShipDate = times.Min();
                info.ResultText = result.dat.Z1[0].d; return info;
            }

            List<Item> list = new List<Item>();
            info.ResultText = "";
            if (result.dat.Z1.Count > 0)
            {
                list.Add(result.dat.Z1[0]);
            }
            if (result.dat.Z2.Count > 0)
            {
                list.Add(result.dat.Z2[0]);
            }

            foreach (Item i in list)
            {
                if (regex.Match(i.c).Success)
                {
                    info.ResultText = i.c + "," + i.z; break;
                }
            }
            if (info.ResultText == "")
            {
                info.ResultText = result.dat.Z0.c + "," + result.dat.Z0.z;
            }

            return info;
        }
    }

    public class UpsAnalyzer : EmsAnalyzer
    {
        public UpsAnalyzer()
        {
            TRACK_URL = "http://www.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100002&_={1}";//ups查询请求url
        }
    }

    public class TntAnalyzer : EmsAnalyzer
    {
        public TntAnalyzer()
        {
            TRACK_URL = "http://www.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100004&_={1}";//tnt查询请求url
        }
    }

    public class DpdAnalyzer : EmsAnalyzer
    {
        public DpdAnalyzer()
        {
            TRACK_URL = "http://www.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100010&_={1}";//dpd查询请求url
        }
    }

    public class AraAnalyzer : EmsAnalyzer
    {
        public AraAnalyzer()
        {
            TRACK_URL = "http://www.17track.net/r/handlertrack.ashx?callback=a&num={0}&et=100006&_={1}";//aramex查询请求url
        }
    }

    public class DhlAnalyzer : IFreightInfoAnalyse
    {
        string DHL_URL = "http://www.cn.dhl.com/shipmentTracking?AWB={0}&countryCode=cn&languageCode=zh&_={1}";//dhl查询请求url
        string DHL_URL_0 = "http://www.cn.dhl.com/shipmentTracking?countryCode=cn&fromDayValue={3}&fromMonthValue={2}&fromYearValue={1}&languageCode=zh&shipperReference={0}&toDayValue={6}&toMonthValue={5}&toYearValue={4}&_={7}";//dhl转单查询
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public DhlAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            var queryUrl = string.Format(DHL_URL, orderNo, DateTime.Now.Ticks);//dhl 查询
            var info = dhlQuery(queryUrl);
            if (info.Status == "没找到")
            {
                DateTime begin = DateTime.Now.AddMonths(-3);
                DateTime end = DateTime.Now;
                queryUrl = string.Format(DHL_URL_0, orderNo, begin.Year, begin.Month.ToString("").PadLeft(2, '0'), begin.Day.ToString().PadLeft(2, '0'), end.Year, end.Month.ToString().PadLeft(2, '0'), end.Day.ToString().PadLeft(2, '0'), DateTime.Now.ToFileTime());//dhl 查询
                info = dhlQuery(queryUrl);//转单查询
            }
            return info;
        }

        private FreightInfo dhlQuery(string queryUrl)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(queryUrl, "GET");
            string html = tools.GetResponseHtml(request);
            JObject result = (JObject)JsonConvert.DeserializeObject(html);
            if (result["errors"] != null)
            {
                info.Status = "没找到"; return info;
            }
            if (result["results"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["results"][0]["delivery"] == null || result["results"][0]["delivery"]["status"] == null)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["results"][0]["delivery"]["status"].ToString() != "delivered")
            {
                info.Status = "n"; return info;
            }

            info = new FreightInfo();
            info.Status = "y";
            info.Deliveried = true;
            DateTime date = DateTime.MinValue;
            if (DateTime.TryParse(result["results"][0]["checkpoints"][((JArray)result["results"][0]["checkpoints"]).Count() - 1]["date"].ToString(), out date))
            {
                info.ShipDate = date;
            }
            info.ResultText = result["results"][0]["signature"]["label"] + " " + result["results"][0]["signature"]["signatory"] + "   " + result["results"][0]["destination"]["value"];
            if (info.ResultText.Contains("快件通过第三方派送无法得到签收结果"))
            {
                return null;
            }
            request.Abort();
            return info;
        }
    }

    public class EcAnalyzer : IFreightInfoAnalyse
    {
        readonly string EC_URL = "http://www.ec-firstclass.org/Details.aspx";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public EcAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(EC_URL, "POST");
            tools.PostData("TrackNums=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);
            var jsonText = Tools.SubString(html, "var result", "}]}");
            if (jsonText == "")
            {
                info.Status = "查询出错"; return info;
            }
            jsonText = Tools.SubString(jsonText, "{", "}]}");
            if (jsonText == "")
            {
                info.Status = "查询出错"; return info;
            }

            JObject result = (JObject)JsonConvert.DeserializeObject(jsonText);
            if (!(bool)result["Success"])
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackSummmary"]["Status"] == null)
            {
                info.Status = "查询出错"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackSummmary"]["Status"].ToString() != "Delivered")
            {
                info.Status = "n"; return info;
            }
            if (result["DetailInfos"][0]["Result"]["TrackDetails"].Count() == 0)
            {
                info.Status = "查询出错"; return info;
            }
            var address = result["DetailInfos"][0]["Result"]["TrackSummmary"]["Address"];
            var text = "妥投 " + address["City"] + "," + address["State"] + "," + address["Country"] + "," + address["Zip"];
            var trackDetails = result["DetailInfos"][0]["Result"]["TrackDetails"];
            text += " " + ((DateTime)trackDetails[trackDetails.Count() - 1]["Date"]).ToShortDateString();
            info = new FreightInfo { Deliveried = true };
            info.ResultText = text;
            request.Abort();
            return info;
        }
    }

    public class RpxAnalyzer : IFreightInfoAnalyse
    {
        readonly string RPX_URL = "http://www.rpxonline.com/index.php?option=com_track&view=tracking";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex regex = new Regex("<div class=\"trace_column tc_date\">.+</div>");

        public RpxAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo();
            var request = tools.SendRequest(RPX_URL, "POST");
            tools.PostData("qType=T&sid=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);

            if (!html.Contains("Delivered"))
            {
                info.Status = "n"; return info;
            }
            int index = html.IndexOf("<h2>Shipment Travel History</h2>");
            if (index < 0)
            {
                info.Status = "查询出错"; return info;
            }
            index = html.IndexOf("Delivered", index);
            if (index < 0)
            {
                info.Status = "查询出错"; return info;
            }
            int end = html.IndexOf("</div>", index);
            if (end < 0)
            {
                info.Status = "查询出错"; return info;
            }
            info.ResultText = html.Substring(index, end - index).Replace("\t", "");
            info.Status = "y";

            var matchs = regex.Matches(html, end);
            Match[] matchArray = new Match[matchs.Count];
            matchs.CopyTo(matchArray, 0);
            List<DateTime> dates = new List<DateTime>();
            DateTime datetime;
            foreach (Match m in matchArray)
            {
                if (m.Success)
                {
                    if (DateTime.TryParse(m.Value.Replace("<div class=\"trace_column tc_date\">", "").Replace("</div>", ""), out datetime))
                    {
                        dates.Add(datetime);
                    }
                }
            }
            info.ShipDate = dates.Min<DateTime>();
            request.Abort();
            return info;
        }
    }

    public class FedexAnalyzer : IFreightInfoAnalyse
    {
        readonly string FEDEX_URL = "https://www.fedex.com/trackingCal/track?action=trackpackages&locale=zh_CN&version=1&format=json&data={%22TrackPackagesRequest%22:{%22appType%22:%22WTRK%22,%22uniqueKey%22:%22%22,%22processingParameters%22:{},%22trackingInfoList%22:[{%22trackNumberInfo%22:{%22trackingNumber%22:%22<ORDERNO>%22,%22trackingQualifier%22:%22%22,%22trackingCarrier%22:%22%22}}]}}&_=";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();

        public FedexAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            string url = FEDEX_URL.Replace("<ORDERNO>", orderNo);
            var request = tools.SendRequest(url + DateTime.Now.Ticks, "GET");
            string html = tools.GetResponseHtmlGzip(request);

            JObject result = (JObject)JsonConvert.DeserializeObject(html);
            var data = result["TrackPackagesResponse"]["packageList"];
            if (data.Count() == 0)
            {
                return info;
            }
            data = data[0];
            if (data["keyStatus"].ToString() != "已送达")
            {
                return info;
            }
            var text = data["statusWithDetails"].ToString();
            int index = text.IndexOf("签收人");
            text = text.Substring(index);
            text += " " + ((DateTime)data["shipDt"]).ToShortDateString();

            info.Status = "y";
            info.ResultText = text;
            request.Abort();
            return info;
        }
    }

    public class AusAnalyzer : IFreightInfoAnalyse
    {
        readonly string AUSPOST_URL = "http://auspost.com.au/track/track.html?exp=b";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex ausLocationRegex = new Regex(@"<div class=""cell-float-right ed-location"">\s+<p>(.*)</p>\s+</div>");
        Regex ausSubmitDateRegex = new Regex(@"<div class=""cell-float-left ed-date"">\s+<p>\s+(.*)\s+</p>\s+</div>");
        Regex regex_p = new Regex("<p>.*</p>");

        public AusAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(AUSPOST_URL, "POST");
            tools.PostData("trackIds=" + orderNo, request);
            string html = tools.GetResponseHtmlGzip(request);

            if (html.Contains("Invalid tracking number"))
            {
                return info;
            }
            int index = html.IndexOf("<p>Delivered</p>");
            if (index < 0)
            {
                info.Status = "n"; return info;
            }
            info.Status = "y";
            info.ResultText = "Delivered";
            index = html.IndexOf("<div id=\"more-details-content\">");
            if (index < 0) { return info; }

            var matchs = ausLocationRegex.Matches(html, index);
            if (matchs.Count > 0)
            {
                if (matchs[0].Success)
                {
                    info.ResultText += "，" + matchs[0].Groups[1].Value;
                }
            }
            matchs = ausSubmitDateRegex.Matches(html, index);
            if (matchs.Count > 0)
            {
                if (matchs[matchs.Count - 1].Success)
                {
                    info.ResultText += "，" + matchs[matchs.Count - 1].Groups[1].Value;
                }
            }

            request.Abort();
            return info;
        }
    }

    public class HyexpAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://www.hyexp.net/cgi-bin/GInfo.dll?EmmisTrackE";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex statusRegex = new Regex(@"<span id='HeaderState'><br>Status \: ([^<]*)</span>");
        Regex signedRegex = new Regex(@"<span id='HeaderSign'><br>Signed for by \: ([^<]*)</span>");
        Regex submitDateRegex = new Regex(@"<td align='center' bgcolor='#F5F9FA' class='trackListOdd'>([^</td>]*)</td>");

        public HyexpAnalyzer()
        {

        }

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(POST_URL, "POST");
            tools.PostData("w=jxhyexp&cno=" + orderNo, request);
            string html = tools.GetResponseHtml(request);

            int index = 0;
            var matchs = statusRegex.Matches(html);
            if (matchs.Count == 0 || !matchs[0].Success || matchs[0].Groups[1].Value.IndexOf("Delivered") < 0)
            {
                return info;
            }
            info.Status = "y";
            index = matchs[0].Index;

            matchs = signedRegex.Matches(html, index);
            if (matchs.Count > 0 && matchs[0].Success)
            {
                info.ResultText += matchs[0].Groups[1].Value;
                index = matchs[0].Index;
            }

            matchs = submitDateRegex.Matches(html, index);
            DateTime time = DateTime.Now;
            DateTime shipDate = DateTime.Now;

            foreach (Match match in matchs)
            {
                if (DateTime.TryParse(match.Groups[1].Value, out time))
                {
                    if (shipDate.CompareTo(time) > 0)
                    {
                        shipDate = time;
                        info.ShipDate = time;
                    }
                }
            }

            request.Abort();
            return info;
        }
    }

    public class SgxAnalyzer : IFreightInfoAnalyse
    {
        readonly string POST_URL = "http://www.sgx-th.com/cgi-bin/GInfo.dll?EmmisTrackJ";
        protected NetTools tools = new NetTools(30);
        protected WebClient client = new WebClient();
        Regex statusRegex = new Regex(@"配達状況：([^<]*)<");
        Regex timeRegex = new Regex(@"<td align='center' bgcolor='[^']+' class='[^']+'>([^</td>]*)</td>");
        Regex infoRegex = new Regex(@"<td align='left' bgcolor='[^']+' class='[^']+'>([^</td>]*)</td>");

        public FreightInfo Analyse(string orderNo)
        {
            FreightInfo info = new FreightInfo { Status = "n" };
            var request = tools.SendRequest(POST_URL, "POST");
            tools.PostData("cno=" + orderNo + "&w=sgx-th", request);
            string html = tools.GetResponseHtml(request, Encoding.GetEncoding("gb2312"));

            int index = 0;
            var matchs = statusRegex.Matches(html);
            if (matchs.Count == 0 || !matchs[0].Success || matchs[0].Groups[1].Value != "配達完了")
            {
                return info;
            }
            info.Status = "y";
            index = matchs[0].Index;

            List<DateTime> dates = new List<DateTime>();
            DateTime time;
            matchs = timeRegex.Matches(html, index);
            for (int i = 0; i < matchs.Count; i++)
            {
                if (DateTime.TryParse(matchs[i].Groups[1].Value, out time))
                {
                    dates.Add(time);
                }
            }

            info.ShipDate = dates.Min();

            matchs = infoRegex.Matches(html, index);
            if (matchs.Count > 1)
            {
                info.ResultText = matchs[matchs.Count - 2].Groups[1].Value;
            }
            request.Abort();
            return info;
        }
    }
}
